using System;
using System.Collections;
using System.Collections.Generic;

namespace System.Collections
{
    /// <summary>
    /// A Stack<> implementation wrapper, which implements IStack<>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public sealed class GenericStack<T> : IStack<T>
    {
        #region Private Variables
        private System.Collections.Generic.Stack<T> _RealStack;
        #endregion

        #region Constructors
        public GenericStack()
            : this(new System.Collections.Generic.Stack<T>())
        {
        }

        public GenericStack(System.Collections.Generic.Stack<T> realStack)
        {
            if (realStack == null)
                throw new ArgumentNullException("realStack");
            this._RealStack = realStack;
        }

        public GenericStack(T[] initialContents)
            :this(new System.Collections.Generic.Stack<T>(initialContents))
        {
        }

        public GenericStack(int capacity)
            :this(new System.Collections.Generic.Stack<T>(capacity))
        {
        }
        #endregion

        #region IStack<T> Members

        public T Peek()
        {
            return _RealStack.Peek();
        }

        public void Push(T value)
        {
            _RealStack.Push(value);
        }

        public T Pop()
        {
            return _RealStack.Pop();
        }

        public T[] Pop(int count)
        {
            System.Collections.Generic.List<T> tl = new System.Collections.Generic.List<T>();
            int xm = this.Count;
            int x = 0;
            for (x = 0; (x < count) && (x < xm); x++)
            {
                tl.Add(this.Pop());
            }
            return tl.ToArray();
        }
        object[] IStack.Pop(int count)
        {
            System.Collections.Generic.List<object> tl = new System.Collections.Generic.List<object>();
            int xm = this.Count;
            int x = 0;
            for (x = 0; (x < count) && (x < xm); x++)
            {
                tl.Add((object)this.Pop());
            }
            return tl.ToArray();
        }

        public bool Contains(T value)
        {
            return _RealStack.Contains(value);
        }

        #endregion

        #region IStack Members

        object IStack.Peek()
        {
            return this.Peek();
        }

        public void Push(object value)
        {
            this.Push((T)value);
        }

        object IStack.Pop()
        {
            return this.Pop();
        }

        public bool Contains(object value)
        {
            return this.Contains((T)value);
        }

        public void Clear()
        {
            _RealStack.Clear();
        }

        #endregion

        #region ICollection Members

        public void CopyTo(Array array, int index)
        {
            ((ICollection)_RealStack).CopyTo(array, index);
        }

        public int Count
        {
            get { return _RealStack.Count; }
        }

        public bool IsSynchronized
        {
            get { return ((ICollection)_RealStack).IsSynchronized; }
        }

        public object SyncRoot
        {
            get { return ((ICollection)_RealStack).SyncRoot; }
        }

        #endregion

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return _RealStack.GetEnumerator();
        }

        #endregion


       #region IStack<T> Members


        public T[] Peek(int count)
        {
            List<T> lResult = new List<T>();
            lResult.AddRange(this.ToArray());
            if (lResult.Count > count)
            {
                lResult.RemoveRange(count, lResult.Count - count);
            }
            return lResult.ToArray();
        }

        public T[] ToArray()
        {
            return _RealStack.ToArray();
        }

        #endregion

        #region IStack Members


        object[] IStack.Peek(int count)
        {
            return ((object[])((Array)this.Peek(count)));
        }

        object[] IStack.ToArray()
        {
            return ((object[])(Array)this.ToArray());
        }

        #endregion
    }
}
